#include "wx/wxprec.h"

#if wxUSE_XRC

#include <wx/propgrid/propgrid.h>
#include <wx/propgrid/xh_propgrid.h>
#define wxXML_GetAttribute(A,B,C)   (A->GetPropVal(B,C))

IMPLEMENT_DYNAMIC_CLASS( wxPropertyGridXmlHandler, wxXmlResourceHandler )

wxPropertyGridXmlHandler::wxPropertyGridXmlHandler()
  : wxXmlResourceHandler(), m_manager( NULL ), m_populator( NULL ) {
  XRC_ADD_STYLE( wxTAB_TRAVERSAL );
  XRC_ADD_STYLE( wxPG_AUTO_SORT );
  XRC_ADD_STYLE( wxPG_HIDE_CATEGORIES );
  XRC_ADD_STYLE( wxPG_BOLD_MODIFIED );
  XRC_ADD_STYLE( wxPG_SPLITTER_AUTO_CENTER );
  XRC_ADD_STYLE( wxPG_TOOLTIPS );
  XRC_ADD_STYLE( wxPG_HIDE_MARGIN );
  XRC_ADD_STYLE( wxPG_STATIC_SPLITTER );
  XRC_ADD_STYLE( wxPG_LIMITED_EDITING );
  XRC_ADD_STYLE( wxPG_TOOLBAR );
  XRC_ADD_STYLE( wxPG_DESCRIPTION );
  XRC_ADD_STYLE( wxPG_EX_INIT_NOCAT );
  XRC_ADD_STYLE( wxPG_EX_HELP_AS_TOOLTIPS );
  XRC_ADD_STYLE( wxPG_EX_AUTO_UNSPECIFIED_VALUES );
  XRC_ADD_STYLE( wxPG_EX_WRITEONLY_BUILTIN_ATTRIBUTES );
  XRC_ADD_STYLE( wxPG_EX_NO_FLAT_TOOLBAR );
  XRC_ADD_STYLE( wxPG_EX_MODE_BUTTONS );
  AddWindowStyles();
}

class wxPropertyGridXrcPopulator : public wxPropertyGridPopulator {
  public:
    wxPropertyGridXrcPopulator( wxPropertyGridXmlHandler* handler )
      : wxPropertyGridPopulator() {
      m_xrcHandler = handler;
      m_prevPopulator = m_xrcHandler->m_populator;
    }

    virtual ~wxPropertyGridXrcPopulator() {
      m_xrcHandler->m_populator = m_prevPopulator;
    }

    virtual void DoScanForChildren() {
      m_xrcHandler->CreateChildrenPrivately( m_pg, NULL );
    }

  protected:
    wxPropertyGridXmlHandler*   m_xrcHandler;
    wxPropertyGridPopulator*    m_prevPopulator;
};

void wxPropertyGridXmlHandler::InitPopulator() {
  wxPropertyGridXrcPopulator* populator = new wxPropertyGridXrcPopulator( this );
  m_populator = populator;
}

void wxPropertyGridXmlHandler::PopulatePage( wxPropertyGridState* state ) {
  wxString sColumns( _T( "columns" ) );
  if( HasParam( sColumns ) ) {
    state->SetColumnCount( GetLong( sColumns ) );
  }
  m_populator->SetState( state );
  m_populator->AddChildren( state->DoGetRoot() );
}

void wxPropertyGridXmlHandler::DonePopulator() {
  delete m_populator;
}

void wxPropertyGridXmlHandler::HandlePropertyGridParams() {
  wxString sVW( _T( "virtualwidth" ) );
  if( HasParam( sVW ) ) {
    int vw = GetLong( sVW );
    m_pg->SetVirtualWidth( vw );
  }
}

wxObject *wxPropertyGridXmlHandler::DoCreateResource() {
  const wxXmlNode* node = m_node;
  wxString nodeName = node->GetName();
  wxString emptyString;
  if( nodeName == _T( "property" ) ) {
    wxString clas = wxXML_GetAttribute( node, _T( "class" ), emptyString );
    wxString label;
    wxString sLabel( _T( "label" ) );
    if( HasParam( sLabel ) ) {
      label = GetText( sLabel );
    }
    wxString name;
    wxString sName( _T( "name" ) );
    if( HasParam( sName ) ) {
      name = GetText( sName );
    } else {
      name = label;
    }
    wxString sValue( _T( "value" ) );
    wxString value;
    wxString* pValue = NULL;
    if( HasParam( sValue ) ) {
      value = GetText( sValue );
      pValue = &value;
    }
    wxXmlNode* choicesNode = GetParamNode( _T( "choices" ) );
    wxPGChoices choices;
    if( choicesNode ) {
      choices = m_populator->ParseChoices( choicesNode->GetNodeContent(),
                                           wxXML_GetAttribute( choicesNode, _T( "id" ), emptyString ) );
    }
    wxPGProperty* property = m_populator->Add( clas, label, name, pValue, &choices );
    if( !property ) {
      return NULL;
    }
    wxString sFlags( _T( "flags" ) );
    wxString flags;
    if( HasParam( sFlags ) ) {
      property->SetFlagsFromString( GetText( sFlags ) );
    }
    wxString sTip( _T( "tip" ) );
    if( HasParam( sTip ) ) {
      property->SetHelpString( GetText( sTip ) );
    }
    if( property->GetChildCount() ) {
      wxPGProperty* pwc = property;
      wxString sExpanded( _T( "expanded" ) );
      if( HasParam( sExpanded ) ) {
        pwc->SetExpanded( GetBool( sExpanded ) );
      }
    }
    m_populator->AddChildren( property );
  } else if( nodeName == _T( "attribute" ) ) {
    wxString s1 = wxXML_GetAttribute( node, _T( "name" ), emptyString );
    if( s1.length() ) {
      m_populator->AddAttribute( s1, wxXML_GetAttribute( node, _T( "type" ), emptyString ), node->GetNodeContent() );
    }
  } else if( m_class == _T( "wxPropertyGrid" ) ) {
    XRC_MAKE_INSTANCE( control, wxPropertyGrid )
    control->Create( m_parentAsWindow, GetID(), GetPosition(), GetSize(), GetStyle(), GetName() );
    m_pg = control;
    HandlePropertyGridParams();
    InitPopulator();
    PopulatePage( control->GetState() );
    DonePopulator();
    SetupWindow( control );
    return control;
  } else if( nodeName == _T( "choices" ) ) {
    m_populator->ParseChoices( node->GetNodeContent(),
                               wxXML_GetAttribute( node, _T( "id" ), emptyString ) );
  } else if( nodeName == _T( "splitterpos" ) ) {
    wxASSERT( m_populator );
    wxString sIndex = wxXML_GetAttribute( node, _T( "index" ), emptyString );
    long index;
    if( !sIndex.ToLong( &index, 10 ) ) {
      index = 0;
    }
    wxString s = node->GetNodeContent();
    long pos;
    if( wxPropertyGridPopulator::ToLongPCT( s, &pos, m_pg->GetClientSize().x ) ) {
      m_populator->GetState()->DoSetSplitterPosition( pos, index, false );
    }
  }
  #if wxPG_INCLUDE_MANAGER
  else if( nodeName == _T( "page" ) ) {
    wxASSERT( m_manager );
    wxString label;
    wxString sLabel( _T( "label" ) );
    if( HasParam( sLabel ) ) {
      label = GetText( sLabel );
    } else {
      label = wxString::Format( _T( "Page %i" ), ( int )( m_manager->GetPageCount() + 1 ) );
    }
    m_manager->AddPage( label );
    wxPropertyGridState* state = m_manager->GetPage( m_manager->GetPageCount() - 1 );
    PopulatePage( state );
  } else if( m_class == _T( "wxPropertyGridManager" ) ) {
    XRC_MAKE_INSTANCE( control, wxPropertyGridManager )
    control->Create( m_parentAsWindow, GetID(), GetPosition(), GetSize(), GetStyle(), GetName() );
    wxPropertyGridManager* oldManager = m_manager;
    m_manager = control;
    m_pg = control->GetGrid();
    HandlePropertyGridParams();
    InitPopulator();
    CreateChildrenPrivately( control, NULL );
    DonePopulator();
    m_manager = oldManager;
    SetupWindow( control );
    return control;
  }
  #endif
  else {
    wxASSERT( false );
  }
  return NULL;
}

bool wxPropertyGridXmlHandler::CanHandle( wxXmlNode *node ) {
#define fOurClass(A) IsOfClass(node, A)
  wxString name = node->GetName();
  return ( ( m_populator && ( name == _T( "property" ) || name == _T( "attribute" ) || name == _T( "choices" ) ||
                              name == _T( "splitterpos" ) ) ) ||
           ( m_manager && name == _T( "page" ) ) ||
           ( !m_populator && fOurClass( _T( "wxPropertyGrid" ) ) )
           #if wxPG_INCLUDE_MANAGER
           || ( !m_populator && fOurClass( _T( "wxPropertyGridManager" ) ) )
           #endif
         );
}

#endif
